#ifndef Define_LcBasic
#define Define_LcBasic


#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include <algorithm>

using namespace std;
using namespace cv;

namespace lc
{
	
	int tryimread(const string filename , Mat & src , int flag = 1);

	Mat gray2alpha(Mat graymask , Mat src);

	float cvCrossProduct(Point & p1,Point & p2,Point & p3);

	int getClockWise(vector<Point>  & co , float eps = 1e-5);

	void appendColorDescriptors(Mat src,vector<Point> & keypts,Mat &desc, string space);

	void colormap(Mat src, Mat &dst, int do_norm = 1);

	void filterRow(Mat & src, Mat & dst, std::vector<int> id);

	void filterCol(Mat & src, Mat & dsc, std::vector<int> id);

	void filterMat(Mat & src, Mat & dsc, std::vector<int> & id);


	Mat colorshow( const std::string  winname, Mat & src);

	float reduceMat( Mat & mat, int rtype);

	float getSAD( Mat & A, Mat & B);

	void gscatter( Mat & img, std::vector<Point2f> points, std::vector<int> id);

	Mat getBase( Mat & data, int m = 3 ,bool if_norm = false);

	Mat getBase( Mat & data, Mat & weight, int m = 3 ,bool if_norm = false);

	Mat getProjMatrix( Mat & base);

	Mat points2Mat( std::vector< Point2f > & ,bool if_norm = false);

	void diffPoints( std::vector<Point2f> & , std::vector<Point2f> & );

	Mat Points2Affine(std::vector<Point2f> & po1,std::vector<Point2f> & po2);
	Mat Points2Affine(Mat & po1,Mat & po2);

	Point2f transbyAffine( Mat & A, Point2f po);

	Mat Points2Homography( std::vector<Point2f> & po1, std::vector<Point2f> & po2);
	Mat Points2Homography(Mat & po1, Mat & po2);

	void randperm( int n, std::vector<int> & ord);

	
	void points2mat(std::vector<Point2f> & po, Mat & mpo);

	void Homo2D( Point2f & src,Point2f & dst, Mat H);

	Mat Affine2Homography( Mat & Affine,vector<Point2f> & po0, vector<Point2f> & po1);

	void LcMat2Bin( const char * file_name, Mat & src);

	void LcBin2Mat( const char * file_name, Mat & ans);

	namespace _Affine2Homography
	{
		void calcErr( Mat & para, Mat & err,Mat & mpo0, Mat & mpo1);
		void calcJac( Mat & para, Mat & jac,Mat & mpo0, Mat & mpo1);
		void para2Homo( Mat & para, Mat & H);
		void Homo2para( Mat & para, Mat & H);
		void calcDeriv(const Mat &err1, const Mat &err2, double h, Mat res);
	};

	class LcSortElement
	{
	public:
		float element;
		int id;
		
		LcSortElement(){;}
		

		//static bool compare( LcSortElement & a, LcSortElement & b);
	};
	
	bool LcSortcompare( const LcSortElement & a, const LcSortElement & b);
	
	
	void argsort( vector<float> & data, vector<int> & id);

	void swapMatrix( Mat & src, Mat & dst);

	void swapMatrix( Mat & src, Mat & dst, Mat & src_lab, Mat & dst_lab);

	Mat randMatrix( Size size);

};

#endif